#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <termios.h>

#include "main.h"
#include "config.debug.h"
#include "bool.h"
#include "string.h"
#include "db.h"

#include "builtin/builtins.h"
#include "builtin/blog.h"


static void *db_handle = NULL;
static bool intr = false;
static bool intr2 = false;

static void
cli_close_db(void)
{
  assert(db_handle != NULL)
  db_close(db_handle);
  db_shutdown();
  db_handle = NULL;
}

static void
sgnl_hndlr(int signo)
{
  if (intr == false) {
    fprintf(stderr, "\n(next? y/N) ");
    intr = true;
    intr2 = false;
  } else if (intr2 == false) {
    fprintf(stderr, "\n(abort? y/N)");
    intr2 = true;
  } else {
    fprintf(stderr, "Got Signal %d: Abort!\n", signo);
    cli_close_db();
    exit(EXIT_FAILURE);
  }
}

static void
setsigs(void)
{
  static struct sigaction sa;

  sa.sa_handler = sgnl_hndlr;
  sa.sa_flags = SA_RESTART;
  sigaction(SIGINT, &sa, NULL);
  sigaction(SIGUSR1, &sa, NULL);
  sigaction(SIGUSR2, &sa, NULL);
}

static void
cli_init_db(void **hndl, const char *path)
{
  assert( path == NULL );
  if (db_set_arg(path) != DB_ERR_OK) {
    E("Error setting db argument (%s)..", path);
    goto error;
  }
  if (db_preinit() != DB_ERR_OK) {
    E2("Error init db..");
    goto error;
  }
  if (db_init(BLOG_DB_PRFIX, hndl) != DB_ERR_OK) {
    E2("Error during db init..");
    goto error;
  }
  return;
error:
  exit(EXIT_FAILURE);
}

static void
readline(string_t **dst, const char *text, size_t max_lines, bool delete_newline)
{
  char *line = NULL;
  size_t len = 0, line_nr = 0;
  ssize_t rsiz;
  string_t *result = (dst ? *dst : create_empty_string());

  if (text) printf("%s? ", text);
  while ( ((rsiz = getline(&line, &len, stdin)) != -1) ) {
    line_nr++;
    if (intr && (strchr(line, 'y') != NULL)) {
      printf("abort ..\n");
      intr = false;
      break;
    } else {
      intr = false;
    }

    add_string(result, line);

    if (max_lines > 0) {
      if (line_nr >= max_lines) {
        break;
      }
    }
    if (text) printf("%s? ", text);
  }
  if (strlen(line) == 0) {
    cli_close_db();
    fprintf(stderr, " exiting..\n");
    exit(3);
  }
  if (line) free(line);
  if (delete_newline) replace_string(result, "\n", "\0", 1);
  *dst = result;
}

char
menu(void) {
  int choice;

again:
  printf("[%s - MENU]\n"
         "[1] - show posts\n"
         "[2] - show post content\n"
         "[3] - new post\n"
         "[4] - new category\n"
         "[5] - new tag\n"
         "[6] - new tagpost\n",
         PACKAGE_NAME);
  if ((choice = getchar()) < '1' || choice > '6') {
    if (choice != '\n') {
      fprintf(stderr, "Unknown choice: %c\n", (char)choice);
      while (getchar() != '\n') { }
    } else {
      fprintf(stderr, "Invalid newline \'\\n\'\n");
    }
    goto again;
  }
  while (getchar() != '\n') { }
  return (choice);
}

int
main(int argc, char **argv)
{
  string_t *limit = NULL;

  if (argc != 2) {
    fprintf(stderr, "need the ncblog db root dir as argument: " \
      "%s [DB_ROOT_DIR]\n", argv[0]);
    return (EXIT_FAILURE);
  }
  fprintf(stderr, "*** COMMAND-LINE-BLOG-EDITOR ***\n");
#ifdef NC_VERSION
  fprintf(stderr, "VERSION: %s\n", NC_VERSION);
#endif

  cli_init_db(&db_handle, argv[1]);
  setsigs();
  switch (menu()) {
    case '1':
      readline(&limit, "Limit Postcount", 1, true);
      //TODO: make blog_show_posts(...) work!
      break;
  }

  free_string(limit);
  cli_close_db();
  return (EXIT_SUCCESS);
}
